<?php
class VectorIterator implements Iterator {
  protected $cursor = 0;
  protected $items = array();
  public function __construct( &$items ) {
    $this->items = &$items;
  }
  
  
  /* Iterator implementation */
  public function current() {
    return is_array( $this->items[$this->cursor] ) ? new Atom( $this->items[$this->cursor] ) : $this->items[$this->cursor];
  }
  
  public function key() {
  	return $this->cursor;
  }
  
  public function next() {
    ++$this->cursor;
    return $this->valid();
  }
  
  public function valid() {
    return is_array( $this->items ) && array_key_exists( $this->cursor, $this->items );
  }
  
  public function rewind() {
    $this->cursor = 0;
  }
  
}



class Vector implements ArrayAccess, IteratorAggregate {
  protected $items = array();
  
  
  /* IteratorAggregate implementation */
  public function getIterator() {
    return new VectorIterator( $this->items );
  }
  
  
  /* ArrayAccess implementation */
  public function offsetExists( $offset ) {
    return is_array( $this->items ) && array_key_exists( $offset, $this->items );
  }
  
  public function offsetGet( $offset ) {
    return $this->items[$offset];
  }
  
  public function offsetSet( $offset, $value ) {
    return $this->items[$offset] = $value;
  }
  
  public function offsetUnset( $offset ) {
    unset( $this->items[$offset] );
  }
  
}

class Atom implements ArrayAccess {
  /**
   * Array of atom's data
   * @var array
   */
  protected $data = array();
  public $template = '';
  
  public function __construct( $data=null ) {
    if ( is_array($data) ) {
      $this->data = $data;
    }
  }
    
  public function __get( $k ) {
    return array_key_exists($k, $this->data)?$this->data[$k]:null;
  }
  
  public function __set( $k, $v ) {
    $this->data[$k] = $v;
  }
  
  
    /* ArrayAccess implementation */
  public function offsetExists( $offset ) {
    return is_array( $this->data ) && array_key_exists( $offset, $this->data );
  }
  
  public function offsetGet( $offset ) {
    return $this->data[$offset];
  }
  
  public function offsetSet( $offset, $value ) {
    return $this->data[$offset] = $value;
  }
  
  public function offsetUnset( $offset ) {
    unset( $this->data[$offset] );
  }
  
  
}
?>